winsafe\comctl\handles/
himagelist.rs

1#![allow(non_camel_case_types, non_snake_case)]
2
3use crate::co;
4use crate::comctl::{ffi, iterators::*, privs::*};
5use crate::decl::*;
6use crate::guard::*;
7use crate::kernel::privs::*;
8use crate::prelude::*;
9
10handle! { HIMAGELIST;
11	/// Handle to an
12	/// [image list](https://learn.microsoft.com/en-us/windows/win32/controls/image-lists).
13}
14
15impl HIMAGELIST {
16	/// Returns an iterator over all icons in the image list, by calling
17	/// [`HIMAGELIST::ExtractIcon`](crate::HIMAGELIST::ExtractIcon) for each
18	/// one.
19	///
20	/// # Examples
21	///
22	/// Collecting the icons into a [`Vec`](std::vec::Vec):
23	///
24	/// ```no_run
25	/// use winsafe::{self as w, prelude::*};
26	///
27	/// let himgl: w::HIMAGELIST; // initialized somewhere
28	/// # let himgl = w::HIMAGELIST::NULL;
29	///
30	/// let icons = himgl.iter()
31	///     .collect::<w::HrResult<Vec<_>>>()?;
32	/// # w::HrResult::Ok(())
33	/// ```
34	#[must_use]
35	pub fn iter(&self) -> impl Iterator<Item = HrResult<DestroyIconGuard>> + '_ {
36		HimagelistIter::new(self)
37	}
38
39	/// [`ImageList_Add`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_add)
40	/// function.
41	///
42	/// A copy of the bitmap is made and stored in the image list, so you're
43	/// free to release the original bitmap.
44	pub fn Add(&self, hbmp_image: &HBITMAP, hbmp_mask: Option<&HBITMAP>) -> HrResult<u32> {
45		match unsafe {
46			ffi::ImageList_Add(
47				self.ptr(),
48				hbmp_image.ptr(),
49				hbmp_mask.map_or(std::ptr::null_mut(), |h| h.ptr()),
50			)
51		} {
52			-1 => Err(co::HRESULT::E_FAIL),
53			idx => Ok(idx as _),
54		}
55	}
56
57	/// [`ImageList_AddIcon`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_addicon)
58	/// macro.
59	///
60	/// A copy of the icon is made and stored in the image list, so you're free
61	/// to release the original icon.
62	pub fn AddIcon(&self, hicon: &HICON) -> HrResult<u32> {
63		match unsafe { ffi::ImageList_ReplaceIcon(self.ptr(), -1, hicon.ptr()) } {
64			-1 => Err(co::HRESULT::E_FAIL),
65			idx => Ok(idx as _),
66		}
67	}
68
69	/// [`ImageList_AddMasked`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_addmasked)
70	/// function.
71	///
72	/// A copy of the bitmap is made and stored in the image list, so you're
73	/// free to release the original bitmap.
74	pub fn AddMasked(&self, hbmp_image: &HBITMAP, color_mask: COLORREF) -> HrResult<u32> {
75		match unsafe { ffi::ImageList_AddMasked(self.ptr(), hbmp_image.ptr(), color_mask.into()) } {
76			-1 => Err(co::HRESULT::E_FAIL),
77			idx => Ok(idx as _),
78		}
79	}
80
81	/// [`ImageList_BeginDrag`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_begindrag)
82	/// function.
83	///
84	/// In the original C implementation, you must call
85	/// [`ImageList_EndDrag`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_enddrag)
86	/// as a cleanup operation.
87	///
88	/// Here, the cleanup is performed automatically, because `BeginDrag`
89	/// returns an
90	/// [`ImageListEndDragGuard`](crate::guard::ImageListEndDragGuard), which
91	/// automatically calls `ImageList_EndDrag` when the guard goes out of
92	/// scope. You must, however, keep the guard alive, otherwise the cleanup
93	/// will be performed right away.
94	///
95	/// # Examples
96	///
97	/// ```no_run
98	/// use winsafe::{self as w, prelude::*};
99	///
100	/// let himgl: w::HIMAGELIST; // initialized somewhere
101	/// # let himgl = w::HIMAGELIST::NULL;
102	///
103	/// let _drag = himgl.BeginDrag(0, w::POINT::new())?; // keep guard alive
104	/// # w::HrResult::Ok(())
105	/// ```
106	pub fn BeginDrag(&self, itrack: u32, hotspot: POINT) -> HrResult<ImageListEndDragGuard<'_>> {
107		unsafe {
108			match ffi::ImageList_BeginDrag(self.ptr(), itrack as _, hotspot.x, hotspot.y) {
109				0 => Err(co::HRESULT::E_FAIL),
110				_ => Ok(ImageListEndDragGuard::new()),
111			}
112		}
113	}
114
115	/// [`ImageList_Create`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_create)
116	/// function.
117	///
118	/// # Examples
119	///
120	/// ```no_run
121	/// use winsafe::{self as w, prelude::*, co};
122	///
123	/// let himgl = w::HIMAGELIST::Create(
124	///     w::SIZE::with(16, 16),
125	///     co::ILC::COLOR32,
126	///     1,
127	///     1,
128	/// )?;
129	///
130	/// // ImageList_Destroy() automatically called
131	/// # w::HrResult::Ok(())
132	/// ```
133	#[must_use]
134	pub fn Create(
135		image_sz: SIZE,
136		flags: co::ILC,
137		initial_size: i32,
138		grow_size: i32,
139	) -> HrResult<ImageListDestroyGuard> {
140		unsafe {
141			match ptr_to_option_handle(ffi::ImageList_Create(
142				image_sz.cx,
143				image_sz.cy,
144				flags.raw(),
145				initial_size,
146				grow_size,
147			)) {
148				None => Err(co::HRESULT::E_FAIL),
149				Some(h) => Ok(ImageListDestroyGuard::new(h)),
150			}
151		}
152	}
153
154	/// [`ImageList_DragMove`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_dragmove)
155	/// function.
156	pub fn DragMove(&self, x: i32, y: i32) -> HrResult<()> {
157		match unsafe { ffi::ImageList_DragMove(self.ptr(), x, y) } {
158			0 => Err(co::HRESULT::E_FAIL),
159			_ => Ok(()),
160		}
161	}
162
163	/// [`ImageList_DragShowNolock`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_dragshownolock)
164	/// function.
165	pub fn DragShowNolock(show: bool) -> HrResult<()> {
166		match unsafe { ffi::ImageList_DragShowNolock(show as _) } {
167			0 => Err(co::HRESULT::E_FAIL),
168			_ => Ok(()),
169		}
170	}
171
172	/// [`ImageList_Draw`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_draw)
173	/// function.
174	pub fn Draw(&self, index: u32, hdc_dest: &HDC, dest: POINT, style: co::ILD) -> HrResult<()> {
175		match unsafe {
176			ffi::ImageList_Draw(self.ptr(), index as _, hdc_dest.ptr(), dest.x, dest.y, style.raw())
177		} {
178			0 => Err(co::HRESULT::E_FAIL),
179			_ => Ok(()),
180		}
181	}
182
183	/// [`ImageList_DrawEx`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_drawex)
184	/// function.
185	pub fn DrawEx(
186		&self,
187		index: u32,
188		hdc_dest: &HDC,
189		dest: POINT,
190		img_portion: Option<SIZE>,
191		background_color: ClrDefNone,
192		foreground_color: ClrDefNone,
193		style: co::ILD,
194	) -> HrResult<()> {
195		match unsafe {
196			ffi::ImageList_DrawEx(
197				self.ptr(),
198				index as _,
199				hdc_dest.ptr(),
200				dest.x,
201				dest.y,
202				img_portion.unwrap_or_default().cx,
203				img_portion.unwrap_or_default().cy,
204				background_color.as_u32(),
205				foreground_color.as_u32(),
206				style.raw(),
207			)
208		} {
209			0 => Err(co::HRESULT::E_FAIL),
210			_ => Ok(()),
211		}
212	}
213
214	/// [`ImageList_Duplicate`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_duplicate)
215	/// function.
216	pub fn Duplicate(&self) -> HrResult<ImageListDestroyGuard> {
217		unsafe {
218			match ptr_to_option_handle(ffi::ImageList_Duplicate(self.ptr())) {
219				None => Err(co::HRESULT::E_FAIL),
220				Some(h) => Ok(ImageListDestroyGuard::new(h)),
221			}
222		}
223	}
224
225	/// [`ImageList_ExtractIcon`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_extracticon)
226	/// macro.
227	///
228	/// A copy of the stored icon is returned.
229	#[must_use]
230	pub fn ExtractIcon(&self, index: u32) -> HrResult<DestroyIconGuard> {
231		self.GetIcon(index, co::ILD::NORMAL)
232	}
233
234	/// [`ImageList_GetBkColor`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_getbkcolor)
235	/// function.
236	#[must_use]
237	pub fn GetBkColor(&self) -> COLORREF {
238		unsafe { COLORREF::from_raw(ffi::ImageList_GetBkColor(self.ptr())) }
239	}
240
241	/// [`ImageList_GetIcon`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_geticon)
242	/// function.
243	///
244	/// A copy of the stored icon is returned.
245	#[must_use]
246	pub fn GetIcon(&self, index: u32, flags: co::ILD) -> HrResult<DestroyIconGuard> {
247		unsafe {
248			match ptr_to_option_handle(ffi::ImageList_GetIcon(self.ptr(), index as _, flags.raw()))
249			{
250				None => Err(co::HRESULT::E_FAIL),
251				Some(h) => Ok(DestroyIconGuard::new(h)),
252			}
253		}
254	}
255
256	/// [`ImageList_GetIconSize`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_geticonsize)
257	/// function.
258	#[must_use]
259	pub fn GetIconSize(&self) -> HrResult<SIZE> {
260		let mut sz = SIZE::default();
261		match unsafe { ffi::ImageList_GetIconSize(self.ptr(), &mut sz.cx, &mut sz.cy) } {
262			0 => Err(co::HRESULT::E_FAIL),
263			_ => Ok(sz),
264		}
265	}
266
267	/// [`ImageList_GetImageCount`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_getimagecount)
268	/// function.
269	#[must_use]
270	pub fn GetImageCount(&self) -> u32 {
271		unsafe { ffi::ImageList_GetImageCount(self.ptr()) as _ }
272	}
273
274	/// [`ImageList_Remove`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_remove)
275	/// function.
276	pub fn Remove(&self, index: Option<u32>) -> HrResult<()> {
277		match unsafe { ffi::ImageList_Remove(self.ptr(), index.map_or(-1, |i| i as _)) } {
278			0 => Err(co::HRESULT::E_FAIL),
279			_ => Ok(()),
280		}
281	}
282
283	/// [`ImageList_ReplaceIcon`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_replaceicon)
284	/// function.
285	///
286	/// A copy of the icon is made and stored in the image list, so you're free
287	/// to release the original icon.
288	pub fn ReplaceIcon(&self, index: u32, hicon_new: &HICON) -> HrResult<u32> {
289		match unsafe { ffi::ImageList_ReplaceIcon(self.ptr(), index as _, hicon_new.ptr()) } {
290			-1 => Err(co::HRESULT::E_FAIL),
291			idx => Ok(idx as _),
292		}
293	}
294
295	/// [`ImageList_SetBkColor`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_setbkcolor)
296	/// function.
297	pub fn SetBkColor(&self, bk_color: Option<COLORREF>) -> Option<COLORREF> {
298		match unsafe { ffi::ImageList_SetBkColor(self.ptr(), bk_color.unwrap_or_default().raw()) } {
299			CLR_NONE => None,
300			c => Some(unsafe { COLORREF::from_raw(c) }),
301		}
302	}
303
304	/// [`ImageList_SetImageCount`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_setimagecount)
305	/// function.
306	///
307	/// # Safety
308	///
309	/// If the size is increased, you must call
310	/// [`HIMAGELIST::ReplaceIcon`](crate::HIMAGELIST::ReplaceIcon) to fill the
311	/// new indexes, otherwise draw operations will be
312	/// unpredictable.
313	pub unsafe fn SetImageCount(&self, new_count: u32) -> HrResult<()> {
314		match unsafe { ffi::ImageList_SetImageCount(self.ptr(), new_count) } {
315			0 => Err(co::HRESULT::E_FAIL),
316			_ => Ok(()),
317		}
318	}
319
320	/// [`ImageList_Write`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_write)
321	/// function.
322	pub fn Write(&self, stream: &impl ole_IStream) -> HrResult<()> {
323		match unsafe { ffi::ImageList_Write(self.ptr(), stream.ptr()) } {
324			0 => Err(co::HRESULT::E_FAIL),
325			_ => Ok(()),
326		}
327	}
328}